package com.wysql.ascost.util;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 上传下载工具类
 */
@Component
public class UploadFileUtil {
    /**
     * 访问名
     */
    static String fileLocation = "/restaurantRes/";


    static String localPath = "c:/performanceUpload/";


    /**
     * 单斜线
     */
    static String singleSlash = "/";
    @Value("${file.uploadUrl}")
    private String uploadPath;
    @Value("${file.staticAccessPath}")
    private String staticAccessPath;

    /**
     * 上传文件
     *
     * @param file 文件
     * @return 返回状态文件url
     */
    public static Map<String, Object> uploadFile(MultipartFile file, String FolderName) {
        String pathString = null;
        String uuid = UUID.randomUUID().toString();
        Calendar calendar = Calendar.getInstance();
        String tm = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1);
        Map<String, Object> map = new HashMap<>();
        if (file != null) {
            //获取上传的文件名称
            String filename = file.getOriginalFilename();
            //chrome会获取到该文件的直接文件名称，IE/Edge会获取到文件上传时完整路径/文件名
            //Check for Unix-style path
            int unixSep = filename.lastIndexOf('/');
            //Check for Windows-style path
            int winSep = filename.lastIndexOf('\\');
            //cut off at latest possible point
            int pos = (winSep > unixSep ? winSep : unixSep);
            if (pos != -1) {
                filename = filename.substring(pos + 1);
            }
            pathString = localPath + FolderName + singleSlash + tm + singleSlash + uuid + singleSlash + filename;
            try {
                File files = new File(pathString);
                if (!files.getParentFile().exists()) {
                    files.getParentFile().mkdirs();
                }
                file.transferTo(files);
                map.put("code", 0);
                map.put("fileUrl", fileLocation + FolderName + singleSlash + tm + singleSlash + uuid + singleSlash + filename);
                map.put("fileName", filename);
                map.put("localPath", pathString);
                return map;
            } catch (Exception e) {
                e.printStackTrace();
                map.put("code", 1);
                map.put("fileUrl", "");
                map.put("fileName", "");
                map.put("localPath", "");
                return map;
            }
        } else {
            map.put("code", 1);
            map.put("fileUrl", "");
            return map;
        }
    }

    /**
     * 下载本地文件
     *
     * @param response -
     * @param address  -
     */
    public static void downLoad(HttpServletResponse response, String address) {
        String path = address;
        // path是指欲下载的文件的路径
        File file = new File(path);
        // 取得文件名
        String filename = file.getName();
        // 以流的形式下载文件
        InputStream fis;
        try {
            fis = new BufferedInputStream(new FileInputStream(path));

            byte[] buffer = new byte[fis.available()];

            fis.read(buffer);

            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.setHeader("Content-Disposition", "attachment; filename=" + new String(filename.getBytes(), "ISO-8859-1"));
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setContentType("application/x-msdownload");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void download(HttpServletRequest request, HttpServletResponse response, HSSFWorkbook hssfWorkbook, String fileName) {
        String userAgent = request.getHeader("User-agent");
        byte[] bytes = userAgent.contains("MSIE") ? fileName.getBytes() : fileName.getBytes(StandardCharsets.UTF_8);
        fileName = new String(bytes, StandardCharsets.ISO_8859_1);
        response.reset();
        response.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName));
        try (OutputStream outputStream = response.getOutputStream()) {
            hssfWorkbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static boolean deleteFile(String delPath) {
        boolean flag = false;
        File file = new File(delPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }

    public Map<String, Object> uploadFile2(MultipartFile file, String FolderName) {
        String pathString = null;
        String uuid = UUID.randomUUID().toString();
        Calendar calendar = Calendar.getInstance();
        String tm = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1);
        Map<String, Object> map = new HashMap<>();
        if (file != null) {
            Long size = file.getSize();
            //获取上传的文件名称
            String filename = file.getOriginalFilename();
            //chrome会获取到该文件的直接文件名称，IE/Edge会获取到文件上传时完整路径/文件名
            //Check for Unix-style path
            int unixSep = filename.lastIndexOf('/');
            //Check for Windows-style path
            int winSep = filename.lastIndexOf('\\');
            //cut off at latest possible point
            int pos = (winSep > unixSep ? winSep : unixSep);
            if (pos != -1) {
                filename = filename.substring(pos + 1);
            }
            pathString = uploadPath + FolderName + singleSlash + tm + singleSlash + uuid + singleSlash + filename;
            try {
                File files = new File(pathString);
                if (!files.getParentFile().exists()) {
                    files.getParentFile().mkdirs();
                }
                file.transferTo(files);
                map.put("code", 0);
                map.put("fileUrl", staticAccessPath + FolderName + singleSlash + tm + singleSlash + uuid + singleSlash + filename);
                map.put("fileName", filename);
                map.put("localPath", pathString);
                map.put("size", size);

                return map;
            } catch (Exception e) {
                e.printStackTrace();
                map.put("code", 1);
                map.put("fileUrl", "");
                map.put("fileName", "");
                map.put("localPath", "");
                return map;
            }
        } else {
            map.put("code", 1);
            map.put("fileUrl", "");
            return map;
        }
    }

    public Map<String, Object> uploadFile3(MultipartFile file, String FolderName) {
        String pathString = null;
        String uuid = UUID.randomUUID().toString();
        Calendar calendar = Calendar.getInstance();
        String tm = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1);
        Map<String, Object> map = new HashMap<>();
        if (file != null) {
            //获取上传的文件名称
            String filename = file.getOriginalFilename();
            //chrome会获取到该文件的直接文件名称，IE/Edge会获取到文件上传时完整路径/文件名
            //Check for Unix-style path
            int unixSep = filename.lastIndexOf('/');
            //Check for Windows-style path
            int winSep = filename.lastIndexOf('\\');
            //cut off at latest possible point
            int pos = (winSep > unixSep ? winSep : unixSep);
            if (pos != -1) {
                filename = filename.substring(pos + 1);
            }
            pathString = uploadPath + FolderName + singleSlash + tm + singleSlash + uuid + singleSlash + filename;
            try {
                File files = new File(pathString);
                if (!files.getParentFile().exists()) {
                    files.getParentFile().mkdirs();
                }
                file.transferTo(files);
                map.put("code", 0);
                map.put("fileUrl", FolderName + singleSlash + tm + singleSlash + uuid + singleSlash + filename);
                map.put("fileName", filename);
                map.put("localPath", pathString);

                return map;
            } catch (Exception e) {
                e.printStackTrace();
                map.put("code", 1);
                map.put("fileUrl", "");
                map.put("fileName", "");
                map.put("localPath", "");
                return map;
            }
        } else {
            map.put("code", 1);
            map.put("fileUrl", "");
            return map;
        }
    }

    /**
     * @Title: repairName
     * @Author: ShengQL
     * @Date: 2024/12/17 10:19
     * @Params: [realname]
     * @Return: String
     * @Description: 对于文件名称中特殊符号的处理
     */
    public static String repairName(String realname) {
        //1、目前仅处理#号
        realname = realname.replaceAll("#", "号");
        return realname;
    }

    //获取单元格各类型值，返回字符串类型
    public static String importExcel(Cell cell, Workbook wb) {
        //判断是否为null或空串
        if (cell==null || cell.toString().trim().equals("")) {
            return "";
        }
        String cellValue = "";
        int cellType=cell.getCellType();
        switch (cellType) {
            //数字包含一般数字和日期，如果是日期的话，不做日期格式化，会输出一个五位数的数字，因此可以根据HSSFDateUtil.isCellDateFormatted(cell)判断是否为日期格式
            case Cell.CELL_TYPE_NUMERIC: // 数字
                /**
                 * format 的值可能为以下这些
                 * yyyy-MM-dd----- 14
                 * yyyy年m月d日----- 31
                 * yyyy年m月--------57
                 * m月d日  -----------58
                 * HH:mm-----------20
                 * h时mm分  --------- 32
                 */
                short format = cell.getCellStyle().getDataFormat();
                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                    SimpleDateFormat sdf = null;
                    if (format == 20 || format == 32) {
                        sdf = new SimpleDateFormat("HH:mm");
                    } else if (format == 14 || format == 31 || format == 57 || format == 58) {
                        // 处理自定义日期格式
                        sdf = new SimpleDateFormat("yyyy-MM-dd");
                        double value = cell.getNumericCellValue();
                        Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value);
                        cellValue = sdf.format(date);
                    }else {// 日期
                        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    }
                    try {
                        cellValue = sdf.format(cell.getDateCellValue());
                    } catch (Exception e) {
                        try {
                            throw new Exception("exception on get date data !".concat(e.toString()));
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
                    }finally{
                        sdf = null;
                    }
                }  else {
                    BigDecimal bd = new BigDecimal(cell.getNumericCellValue());
                    cellValue = bd.setScale(4, RoundingMode.HALF_UP).toPlainString();// 数值 这种用BigDecimal包装再获取plainString，可以防止获取到科学计数值
                }
                break;
            case Cell.CELL_TYPE_STRING: // 字符串
                cellValue = cell.getStringCellValue();
                break;
            case Cell.CELL_TYPE_BOOLEAN: // Boolean
                cellValue = cell.getBooleanCellValue()+"";;
                break;
            case Cell.CELL_TYPE_FORMULA: // 公式
                //cellValue = cell.getCellFormula();//获取公式名称，如A1+B1
                //这样对于字符串cell.getStringCellValue()方法即可取得其值，如果公式生成的是数值，使用cell.getStringCellValue()方法
                //会抛出IllegalStateException异常，在异常处理中使用cell.getNumericCellValue();即可。
                try {
                    cellValue = String.valueOf(cell.getStringCellValue());
                } catch (IllegalStateException e) {
                    //cellValue = String.valueOf(cell.getNumericCellValue());
                    BigDecimal bd = new BigDecimal(cell.getNumericCellValue());
                    cellValue = bd.setScale(2,BigDecimal.ROUND_DOWN).toPlainString();
                }
//                System.out.println("公式为："+cell.getCellFormula()+",值为："+cellValue);
                break;
            case Cell.CELL_TYPE_BLANK: // 空值
                cellValue = "";
                break;
            case Cell.CELL_TYPE_ERROR: // 故障
                cellValue = "ERROR VALUE";
                break;
            default:
                cellValue = "UNKNOW VALUE";
                break;
        }
        return cellValue;
    }
}
